<template>
  <teleport to="body"
    ><template v-if="isRender"
      ><transition name="dynamic-mark"
        ><div class="dynamic-mark" v-show="showDialog">
          <div class="dynamic-box flex">
            <transition name="dynamic"
              ><div
                class="dynamic"
                id="dynamic"
                ref="dynamicRef"
                v-show="showDialog"
                v-draggable="{}"
              >
                <dynamic-header
                  :usr-info="usrInfo"
                  :self-id="user.userId"
                  :show-loading-dynamic="
                    Boolean(
                      ((dynamicDatas.isReload && !isSelf) ||
                        (mySelfDynamicDatas.isReload && isSelf) ||
                        (isHaveNew && !isSelf)) &&
                        !isError &&
                        currentDynamicDatas.size
                    )
                  "
                  :is-requesting="isRequesting"
                  :dynamic-ele="dynamicRef!"
                  :dynamic-data-ref="dynamicDataRef"
                  @close-dialog="closeDialog"
                ></dynamic-header>
                <div class="dynamic-main">
                  <div v-if="showDynamic">
                    <div
                      id="dynamicDatas"
                      class="dynamic-main__dynamicDatas"
                      v-if="currentDynamicDatas.size"
                    >
                      <dynamic-data
                        ref="dynamicDataRef"
                        :data="currentDynamicDatas"
                        v-model:is-last="isLast"
                        :self-id="user.userId"
                        :other-id="usrInfo.userId"
                        :is-self="isSelf"
                        :is-friend="isFriend"
                      ></dynamic-data>
                    </div>
                    <div class="dynamic-main__empty" v-else>
                      <SvgIcon icon-class="emptyDynamic" popper-class="empty-icon" />
                      <p>暂无新的动态</p>
                    </div>
                  </div>
                  <div class="dynamic-main__isLoading" v-else>
                    <feed-back
                      :is-requesting="isRequesting"
                      :is-error="isError"
                      message="请求出错啦"
                      @retry="retryRequest"
                    ></feed-back>
                  </div>
                </div></div
            ></transition>
          </div></div></transition></template
  ></teleport>
</template>

<script lang="ts" setup>
import { ref, watch, nextTick, provide } from "vue";
import { getScrollWid } from "@/plugins/getScrollWid";
import { useDynamicPinia } from "@/pinia/dynamic";
import { storeToRefs } from "pinia";
import feedBack from "@/components/ui-components/feedBack.vue";
import { useUserPinia } from "@/pinia/user";
import vDraggable from "@/directives/draggable";
import dynamicData from "./dynamicData.vue";
import Cookie from "@/plugins/cookie";
import subscribe from "./subscribe";
import dynamicHeader from "./dynamicHeader.vue";

const props = withDefaults(
  defineProps<{
    modelValue: boolean;
    usrInfo: User & { bkImg: string };
    isSelf?: boolean;
    isFriend?: boolean;
  }>(),
  {
    isSelf: false,
    isFriend: true,
  }
);

const emits = defineEmits<{
  (e: "update:modelValue", show: boolean): void;
}>();

const dynamicStore = useDynamicPinia();
const { dynamicDatas, mySelfDynamicDatas } = storeToRefs(dynamicStore);
const { user } = storeToRefs(useUserPinia());

/**
 * 当前展示的动态数据
 */
const currentDynamicDatas = ref<Map<string, Dynamic>>(new Map());

/**
 * 浏览器的可视高度改变则组件的根元素的高度也随之改变
 */
const handleToWid: () => void = (): void => {
  // 获取浏览器的可视高度
  const hei: number =
    globalThis.innerHeight ||
    document.body.clientHeight ||
    document.documentElement.clientHeight;
  // 获取浏览器的可视宽度
  const wid: number =
    globalThis.innerWidth ||
    document.body.clientWidth ||
    document.documentElement.clientWidth;
  if (document.body.scrollHeight > hei || document.body.scrollWidth > wid)
    document.body.style.cssText += `overflow: hidden;padding-right: ${getScrollWid()}px`;
  else if (document.body.scrollHeight <= hei || document.body.scrollWidth <= wid)
    document.body.style.cssText = "";
};

/**
 * 是否显示确认操作的对话框
 */
const isRender = ref<boolean>(false);
/**
 * 是否显示确认操作的对话框的内容
 */
const showDialog = ref<boolean>(false);
/**
 * 是否显示好友的详情信息
 */
const showDynamic = ref<boolean>(false);
/**
 * 是否正在发送请求
 */
const isRequesting = ref<boolean>(false);
/**
 * 请求是否出错
 */
const isError = ref<boolean>(false);
/**
 * 请求得到的动态数据是否为最后一页
 */
const isLast = ref<boolean>(false);

// 请求动态数据
const requestDynamic = (payload: {
  userId: string;
  senderId: string;
  dynamicId?: string;
  isSelfDynamic?: boolean;
}): Promise<{ code: number; datas: Map<string, Dynamic>; isLast: boolean }> => {
  return new Promise<{ code: number; datas: Map<string, Dynamic>; isLast: boolean }>(
    (resolve, reject) => {
      if (isError.value) isError.value = false;
      if (showDynamic.value) showDynamic.value = false;
      isRequesting.value = true;
      dynamicStore
        .getDynamic(payload)
        .then((res) => {
          let datas: Map<string, Dynamic> = new Map();
          // 是否为最后一页数据
          let theIsLast: boolean = false;
          isRequesting.value = false;
          if (res.code === 1) {
            showDynamic.value = true;
            if (props.usrInfo.userId === user.value.userId)
              props.isSelf
                ? (datas = mySelfDynamicDatas.value.value)
                : (datas = dynamicDatas.value.value);
            else {
              datas = res.dynamicDatas;
              theIsLast = res.isLast;
            }
          } else isError.value = true;
          resolve({ code: res.code, datas, isLast: theIsLast });
        })
        .catch(() => {
          isRequesting.value = false;
          isError.value = true;
          reject();
        });
    }
  );
};

// 接收新的动态数据
const recieveNewDatas = (payload: {
  userId: string;
  senderId: string;
  firstDynamicId: string;
  dynamicId?: string;
  isSelfDynamic?: boolean;
}) => {
  return new Promise<{ code: number; datas: Map<string, Dynamic>; isLast: boolean }>(
    (resolve, reject) => {
      isRequesting.value = true;
      dynamicStore
        .getDynamic(payload)
        .then((res) => {
          let datas: Map<string, Dynamic> = new Map();
          // 是否为最后一页数据
          let theIsLast: boolean = false;
          isRequesting.value = false;
          if (res.code === 1 && props.usrInfo.userId === user.value.userId) {
            payload.isSelfDynamic
              ? (datas = mySelfDynamicDatas.value.value)
              : (datas = dynamicDatas.value.value);
          }
          resolve({ code: res.code, datas, isLast: theIsLast });
        })
        .catch(() => {
          isRequesting.value = false;
          reject();
        });
    }
  );
};

/**
 * 是否有新的动态
 */
const isHaveNew = ref<boolean>(false);
// 当请求动态数据失败时再次发送请求
const retryRequest = () => {
  if (props.usrInfo.userId === user.value.userId) {
    function requestSelf() {
      requestDynamic({
        userId: user.value.userId,
        senderId: user.value.userId,
        isSelfDynamic: true,
      }).then((res) => {
        if (res.code === 1) {
          currentDynamicDatas.value = res.datas;
          isLast.value = mySelfDynamicDatas.value.isLast;
        }
      });
    }
    // 如果查看的是动态
    if (!props.isSelf) {
      function requestNoSelf() {
        return new Promise<boolean>((resolve, reject) => {
          requestDynamic({
            userId: user.value.userId,
            senderId: user.value.userId,
          })
            .then((res) => {
              if (res.code === 1) {
                currentDynamicDatas.value = res.datas;
                resolve(true);
              } else resolve(false);
              isLast.value = dynamicDatas.value.isLast;
            })
            .catch(() => reject());
        });
      }
      if (!dynamicDatas.value.isRequest)
        requestNoSelf().then((value: boolean) => {
          if (value) subscribe(Cookie.getCookie("token"));
        });
      else if (dynamicDatas.value.isHasNew || dynamicDatas.value.isReload) {
        if (isError.value || !dynamicDatas.value.value.size) requestNoSelf();
        else {
          if (dynamicDatas.value.isHasNew) isHaveNew.value = true;
          recieveNewDatas({
            userId: user.value.userId,
            senderId: user.value.userId,
            firstDynamicId: [...dynamicDatas.value.value][0][0],
          }).then((res) => {
            if (res.code === 1) currentDynamicDatas.value = res.datas;
            isLast.value = dynamicDatas.value.isLast;
            isHaveNew.value = false;
          });
        }
      } else {
        currentDynamicDatas.value = dynamicDatas.value.value;
        showDynamic.value = true;
        isLast.value = dynamicDatas.value.isLast;
        if (!currentDynamicDatas.value.size && !isLast.value) requestNoSelf();
      }
    } else if (!mySelfDynamicDatas.value.isRequest)
      // 如果只是查看自己的动态
      requestSelf();
    else if (mySelfDynamicDatas.value.isReload) {
      if (isError.value || !mySelfDynamicDatas.value.value.size) requestSelf();
      else
        recieveNewDatas({
          userId: user.value.userId,
          senderId: user.value.userId,
          isSelfDynamic: true,
          firstDynamicId: [...mySelfDynamicDatas.value.value][0][0],
        }).then((res) => {
          if (res.code === 1) {
            currentDynamicDatas.value = res.datas;
            isLast.value = mySelfDynamicDatas.value.isLast;
          }
        });
    } else {
      currentDynamicDatas.value = mySelfDynamicDatas.value.value;
      showDynamic.value = true;
      isLast.value = mySelfDynamicDatas.value.isLast;
    }
  } else
    requestDynamic({
      userId: props.usrInfo.userId,
      senderId: user.value.userId,
    }).then((res) => {
      if (res.code === 1) {
        currentDynamicDatas.value = res.datas;
        isLast.value = res.isLast;
      }
    });
};

/**
 * 给该组件一个ref属性
 */
const dynamicRef = ref<HTMLDivElement>();

watch(
  () => props.modelValue,
  (show: boolean) => {
    if (show) {
      window.addEventListener("resize", handleToWid);
      isRender.value = true;
      nextTick(() => {
        showDialog.value = true;
        handleToWid();
        retryRequest();
      });
    } else {
      window.removeEventListener("resize", handleToWid);
      isError.value = false;
      showDialog.value = false;
      document.body.style.cssText = "";
      if (dynamicRef.value) dynamicRef.value.style.transform = "";
      setTimeout(() => (isRender.value = false), 300);
    }
  },
  { immediate: true }
);

/**
 * 给动态数据组件一个ref属性
 */
const dynamicDataRef = ref<any>();

/**
 * 是否正在点赞
 */
const isLoadingThumb = ref<boolean>(false);
provide("isLoadingThumb", isLoadingThumb);
// 关闭动态
const closeDialog = () => {
  if (!isRequesting.value && !isLoadingThumb.value) emits("update:modelValue", false);
};
</script>

<style lang="scss" scoped>
.dynamic {
  &-enter-active,
  &-leave-active {
    transition: transform 0.3s;
  }

  &-enter-from,
  &-leave-to {
    transform: translateY(-30px);
  }

  &-mark {
    position: fixed;
    inset: 0;
    z-index: 1000;
    @include fade(0.25s, ease);
    overflow: auto;
  }

  &-box {
    min-height: 565px;
    @include setWidHei(100%, 100%);
  }

  position: relative;
  width: 480px;
  box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, 0.04), 0px 8px 20px rgba(0, 0, 0, 0.08);
  background-color: #fff;

  &-main {
    padding: 10px 10px 5px 22px;

    &__isLoading {
      height: 140px;
    }

    &__empty {
      color: #cdcdcd;
      text-align: center;
      height: 150px;

      .empty-icon {
        font-size: 100px;
      }
    }

    &__dynamicDatas {
      position: relative;
    }
  }
}
</style>
